package com.explment.lens.utils.jwt;


import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * JWT工具类，token提供者和刷新
 */
@Component
@Data
public class JwtTokenProvider {
    @Value("${jwt.secret}")
    private String secretKey;

    @Value("${jwt.access-expiration}")
    private long accessExpiration;

    @Value("${jwt.refresh-expiration}")
    private long refreshExpiration;

    /**
     * 生成访问令牌
     * 当前使用
     * @param username 用户名
     * @return 生成的JWT令牌字符串
     */
    public String generateAccessToken(String username) {
        return Jwts.builder()
                .setSubject(username)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + accessExpiration))
                .signWith(SignatureAlgorithm.HS256, secretKey)
                .compact();
    }

    /**
     * 生成刷新令牌
     *  一周刷新一次
     * @param username 用户名
     * @return 生成的刷新令牌
     */
    public String generateRefreshToken(String username) {
        return Jwts.builder()
                .setSubject(username)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + refreshExpiration))
                .signWith(SignatureAlgorithm.HS256, secretKey)
                .compact();
    }
    /**
     * 从JWT令牌中提取用户名
     *
     * @param token JWT令牌字符串
     * @return 提取的用户名
     */
    public  String getUsernameFromToken(String token) {
        try {
            return Jwts.parser()
                    .setSigningKey(secretKey)
                    .parseClaimsJws(token)
                    .getBody()
                    .getSubject();
        } catch (JwtException e) {
            throw new JwtException("Failed to parse JWT token", e);
        }
    }

    /**
     * 验证JWT令牌的有效性
     *
     * @param token 需要验证的JWT令牌
     * @return 如果令牌有效则返回true，否则返回false
     * @throws Exception 如果在解析令牌时发生异常，会抛出异常
     */
    public  boolean validateToken(String token) {
        try {
            Claims claims = Jwts.parser()
                    .setSigningKey(secretKey)
                    .parseClaimsJws(token)
                    .getBody();

            // 检查过期时间
            Date expiration = claims.getExpiration();
            if (expiration.before(new Date())) {
                return false;
            }
            return true;
        } catch (Exception e) {
            // 捕获签名无效、令牌格式错误等异常
            return false;
        }
    }
}
